package com.tbnet.java.androidx;

import com.tbnet.java.androidx.utils.Helper;
import org.apache.commons.io.FileUtils;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.List;

public class MainWindow implements ActionListener, ItemListener, ChangeListener {

    private final static Map<String, String> SUPPORT_MAP = new HashMap<String, String>() {
        {
            put("android.support.v4.content.LocalBroadcastManager", "androidx.localbroadcastmanager.content.LocalBroadcastManager");
            put("android.support.v4.widget.PopupWindowCompat", "androidx.core.widget.PopupWindowCompat");
            put("android.support.v4.util.SimpleArrayMap", "androidx.collection.SimpleArrayMap");
            put("android.support.v4.content.PermissionChecker", "androidx.core.content.PermissionChecker");
            put("android.support.annotation.", "androidx.annotation.");
        }
    };

    private JFrame frame;
    private JLabel lblModulePath;
    private JTextField textModulePath;
    private JLabel lblEnvironment;
    private JComboBox<String> boxEnvironment;


    private JScrollPane logScrollPane;
    private JTextArea logTextArea;
    private JButton btnSwitch;


    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            try {
                MainWindow window = new MainWindow();
                window.frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

    /**
     * Create the application.
     */
    public MainWindow() {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
        frame = new JFrame();
        frame.setBounds(100, 100, 600, 450);
        frame.setMinimumSize(new Dimension(600, 400));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setTitle("切换androidx库");

        lblModulePath = new JLabel("工程Module目录");

        textModulePath = new JTextField();
        textModulePath.setColumns(10);
        enableDragAndDrop(textModulePath);

        lblEnvironment = new JLabel("切换环境");

        boxEnvironment = new JComboBox<String>();
        boxEnvironment.addItem("请选择");
        boxEnvironment.addItem("support库");
        boxEnvironment.addItem("androidx库");
        boxEnvironment.addItemListener(this);


        btnSwitch = new JButton("切换");
        btnSwitch.setEnabled(false);
        btnSwitch.addActionListener(this);

        logTextArea = new JTextArea();
        logTextArea.setEditable(false);
        logTextArea.setLineWrap(true);
        logTextArea.setWrapStyleWord(true);

        logScrollPane = new JScrollPane(logTextArea);

        // 布局代码由WindowBuilder生成
        // https://projects.eclipse.org/projects/tools.windowbuilder
        GroupLayout groupLayout = new GroupLayout(frame.getContentPane());
        groupLayout.setHorizontalGroup(
                groupLayout.createParallelGroup(GroupLayout.Alignment.TRAILING)
                        .addGroup(groupLayout.createSequentialGroup()
                                .addGroup(groupLayout.createParallelGroup(GroupLayout.Alignment.TRAILING)
                                        .addGroup(GroupLayout.Alignment.LEADING, groupLayout.createSequentialGroup()
                                                .addGap(19)
                                                .addComponent(lblModulePath)
                                                .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                                                .addComponent(textModulePath, GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE))
                                        .addGroup(GroupLayout.Alignment.LEADING, groupLayout.createSequentialGroup()
                                                .addGap(19)
                                                .addComponent(lblEnvironment)
                                                .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                                                .addComponent(boxEnvironment, GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE))
                                        .addGroup(GroupLayout.Alignment.LEADING, groupLayout.createSequentialGroup()
                                                .addContainerGap()
                                                .addComponent(logScrollPane, GroupLayout.DEFAULT_SIZE, 438, Short.MAX_VALUE))
                                        .addGroup(GroupLayout.Alignment.LEADING, groupLayout.createSequentialGroup()
                                                .addContainerGap()
                                                .addComponent(btnSwitch, GroupLayout.DEFAULT_SIZE, 444, Short.MAX_VALUE)))
                                .addContainerGap()
                        )
        );
        groupLayout.setVerticalGroup(
                groupLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
                        .addGroup(groupLayout.createSequentialGroup()
                                .addContainerGap()
                                .addGroup(groupLayout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                                        .addComponent(textModulePath, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
                                        .addComponent(lblModulePath))
                                .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                                .addGroup(groupLayout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                                        .addComponent(boxEnvironment, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
                                        .addComponent(lblEnvironment))
                                .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(logScrollPane, GroupLayout.DEFAULT_SIZE, 181, Short.MAX_VALUE)
                                .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(btnSwitch)
                                .addContainerGap())
        );

        frame.getContentPane().setLayout(groupLayout);
    }

    // 组件添加拖拽事件
    private void enableDragAndDrop(Component component) {
        DropTarget dropTarget = new DropTarget(component, new DropTargetListener() {

            @Override
            public void dropActionChanged(DropTargetDragEvent dtde) {
                // TODO Auto-generated method stub

            }

            @Override
            public void drop(DropTargetDropEvent dtde) {
                // TODO Auto-generated method stub
                dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
                try {
                    Transferable transferable = dtde.getTransferable();
                    if (transferable.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
                        List<File> fileList = (List<File>) transferable.getTransferData(DataFlavor.javaFileListFlavor);
                        if (fileList != null && fileList.size() > 0) {
                            File file = fileList.get(0);

                            DropTarget dropTarget = (DropTarget) dtde.getSource();
                            JTextField textField = (JTextField) dropTarget.getComponent();
                            textField.setText(file.getAbsolutePath());
                            dtde.dropComplete(true);
                        }
                    } else {
                        dtde.rejectDrop();
                    }
                } catch (UnsupportedFlavorException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    dtde.dropComplete(false);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    dtde.dropComplete(false);
                }
            }

            @Override
            public void dragOver(DropTargetDragEvent dtde) {
                // TODO Auto-generated method stub

            }

            @Override
            public void dragExit(DropTargetEvent dte) {
                // TODO Auto-generated method stub
            }

            @Override
            public void dragEnter(DropTargetDragEvent dtde) {
                // TODO Auto-generated method stub
            }
        });
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == btnSwitch) {
            btnSwitch.setEnabled(false);
            final int environmentIndex = boxEnvironment.getSelectedIndex();
            Thread switchThread = new Thread(() -> {
                doSwitch(environmentIndex);
                SwingUtilities.invokeLater(() -> btnSwitch.setEnabled(true));
            });
            switchThread.start();
        }
    }

    private void doSwitch(int index) {
        final String modulePath = textModulePath.getText();
        if (Helper.isNotEmpty(modulePath)) {
            final File modulePathFile = new File(modulePath);
            if (modulePathFile.exists()) {
                final List<File> files = searchFile(modulePathFile);
                if (files != null && !files.isEmpty()) {
                    for (File file : files) {
                        try {
                            final List<String> srcLines = FileUtils.readLines(file, "UTF-8");
                            if (srcLines != null && !srcLines.isEmpty()) {
                                List<String> destLines = new ArrayList<>();
                                boolean reload = false;
                                for (String line : srcLines) {
                                   boolean lineAdd = false;
                                    if (index == 1) {
                                        final Collection<String> values = SUPPORT_MAP.values();
                                        for (String value : values) {
                                            if (line.contains(value)) {
                                                String key = null;
                                                for (Map.Entry<String, String> entry : SUPPORT_MAP.entrySet()) {
                                                    if (value.equals(entry.getValue())) {
                                                        key = entry.getKey();
                                                        break;
                                                    }
                                                }
                                                if (Helper.isNotEmpty(key)) {
                                                    destLines.add(line.replace(value, key));
                                                    reload = true;
                                                    lineAdd = true;
                                                    break;
                                                }
                                            }
                                        }
                                    } else if (index == 2) {
                                        final Set<String> keys = SUPPORT_MAP.keySet();
                                        for (String key : keys) {
                                            if (line.contains(key)) {
                                                final String value = SUPPORT_MAP.get(key);
                                                if (Helper.isNotEmpty(value)) {
                                                    destLines.add(line.replace(key, value));
                                                    reload = true;
                                                    lineAdd = true;
                                                    break;
                                                }
                                            }
                                        }

                                    }
                                    if (!lineAdd) {
                                        destLines.add(line);
                                    }
                                }
                                if (reload) {
                                    log("处理文件 " + file.getAbsolutePath());
                                    FileUtils.writeLines(file, "UTF-8", destLines, false);
                                }
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            } else {
                log("工程module路径出错");
            }
        } else {
            log("工程module路径出错");
        }
    }

    private List<File> searchFile(File moduleFile) {
        final File[] files = moduleFile.listFiles();
        if (files != null && files.length > 0) {
            final List<File> resultFiles = new ArrayList<>();
            for (File file : files) {
                if (file.isFile()) {
                    resultFiles.add(file);
                } else {
                    if (file.isDirectory()) {
                        final List<File> fList = searchFile(file);
                        if (fList != null && !fList.isEmpty()) {
                            resultFiles.addAll(fList);
                        }
                    }
                }
            }
            return resultFiles;
        }
        return null;
    }


    @Override
    public void itemStateChanged(ItemEvent e) {
        if (boxEnvironment.getSelectedIndex() == 0) {
            btnSwitch.setEnabled(false);
        } else {
            btnSwitch.setEnabled(true);
        }

    }

    @Override
    public void stateChanged(ChangeEvent e) {

    }

    private void log(String line, String... params) {
        try {
            this.logTextArea.append(String.format(line, params));
            this.logTextArea.append(System.lineSeparator());

            this.logTextArea.setCaretPosition(this.logTextArea.getDocument().getLength());
        } catch (Exception e) {
        }
    }
}
